#include "scenario.h"
#include "context_ptr.h"
#include "examples.h"
#include "step.h"
#include "table.h"

using namespace CppStory;

Scenario::Scenario(const char* f, const int l)
: file(f)
, line(l)
, cur_step(NULL)
, examples(NULL)
{
}

Scenario::~Scenario()
{
    if (NULL != examples)
        delete examples;

    std::vector< Step* >::iterator step_iter = steps.begin();
    while (step_iter != steps.end())
    {
        delete *step_iter;
#ifdef WIN32
        step_iter = steps.erase(step_iter);
#else
        steps.erase(step_iter);
#endif
    }
}

void Scenario::register_step(Step *c)
{
    steps.push_back(c);
    cur_step = c;
}

void Scenario::set_name(std::string n)
{
    name = n;
}

void Scenario::create_examples()
{
    examples = new Examples();
}

bool Scenario::run()
{
    bool ret = true;
    if (NULL != get_examples() && NULL != get_examples()->get_table())
    {
        Table* table = get_examples()->get_table();
        for (int row = 0; row < table->get_row_count(); row++)
        {
            std::vector< Step* >::iterator step_iter;
            for (step_iter = steps.begin();
                 step_iter != steps.end();
                 ++step_iter)
            {
                for (int col = 0; col < table->get_col_count(); col++)
                {
                    if ((*step_iter)->replace(table->get_head_name(col), table->get_data(row, col)))
                    {
                        (*step_iter)->get_step_def()->match(*step_iter, (*step_iter)->get_name());
                        break;
                    }
                }
            }
            ret = run_all_steps();
            clean_contexts();
            if (!ret)
                break;
        }
    }
    else
    {
        ret = run_all_steps();
        clean_contexts();
    }
    return ret;
}

bool Scenario::run_all_steps()
{
    bool ret = true;
    std::vector< Step* >::iterator step_iter;
    for (step_iter = steps.begin();
         step_iter != steps.end();
         ++step_iter)
    {
        if (!(*step_iter)->run())
        {
            ret = false;
            break;
        }
    }
    if (0 == steps.size())
        ret = false;
    return ret;
}

void Scenario::clean_contexts()
{
    std::vector< Step* >::iterator step_iter;
    for (step_iter = steps.begin();
         step_iter != steps.end();
         ++step_iter)
    {
        if ((*step_iter)->get_step_def())
        {
            (*step_iter)->get_step_def()->clean_context_ptrs();
        }
    }
}

